﻿using System;
using System.Collections;
//using System.Xml;
//using System.Xml.Schema;
using System.Runtime.Serialization;
using System.IO;
using System.Threading;
//using System.Xml.Serialization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SoftwareConsulting.Interfaces.BasicEntities;
using SoftwareConsulting.BI11.Studio.InternalServices;

namespace SoftwareConsulting.BI11.Studio.BasicEntities
{    
    /// <summary>
    /// Класс умной хэш-таблицы
    /// </summary>
    [Serializable]
    public class SmartHash<T> : Hashtable, ISmartHash<T> where T:IUnique
    {

        public new IEnumerator<T> GetEnumerator()
        {
            lock (this.SyncRoot)
            {
                IEnumerator colEnumerator = base.GetEnumerator();
                while (colEnumerator.MoveNext())
                {
                    yield return (T)((DictionaryEntry)colEnumerator.Current).Value;
                }
            }            
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }        

        /// <summary>
        /// Возвращает элемент, свойство которого равно необходимому значению
        /// </summary>        
        /// <returns></returns>        
        public T GetElementByPropertyValue(string propertyName, object needValue)
        {            
            foreach(T val in this)
            {                
                if (GeneralMethods.Identical(val.GetType().GetProperty(propertyName).GetValue(val, null), needValue))
                {
                    return val;
                }
            }
            return default(T);
        }

        /// <summary>
        /// Возвращает все элементы, свойство которых равно необходимому значению
        /// </summary>        
        /// <returns></returns>        
        public ISmartHash<T> GetAllElementsByPropertyValue(string propertyName, object needValue)
        {
            ISmartHash<T> all = new SmartHash<T>();
            foreach(T val in this)
            {                
                Type t = val.GetType();
                if (GeneralMethods.Identical(t.GetProperty(propertyName).GetValue(val, null), needValue))
                {                    
                    all.Add(t.GetProperty("id").GetValue(val, null), val);
                }
            }
            return all;
        }

        protected SmartHash( SerializationInfo info, StreamingContext context ):
            base(info,context)
        {            
        }

        public SmartHash() :
            base()
        {         
        }
    }
    
    /*public sealed class SmartSerializableHash<T> : SmartHash<T>, IXmlSerializable where T:IUnique
    {       
        public void Serialize(Stream stream)
        {
            XmlSerializer xs = new XmlSerializer(typeof(SmartSerializableHash<T>), "");
            xs.Serialize(stream, this);
        }

        XmlSchema IXmlSerializable.GetSchema()
        {
            return null;
        }

        public IDictionary Deserialize(Stream stream)
        {
            XmlSerializer xs = new XmlSerializer(typeof(SmartSerializableHash<T>), "");
            SmartSerializableHash<T> ds = (SmartSerializableHash<T>)xs.Deserialize(stream);
            return ds;
        }        

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            bool isNonEmpty = true;
            //чтобы нормально распознавал <phrases />
            if (reader.IsEmptyElement)
            {
                isNonEmpty = false;
            }            
            reader.Read();
            if (isNonEmpty)
            {
                if (reader.IsStartElement("item"))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(T), "");
                    while (reader.NodeType != XmlNodeType.EndElement)
                    {
                        reader.ReadStartElement("item");
                        Guid id = new Guid(reader.ReadElementString("key"));
                        reader.ReadStartElement("value");
                        T value = (T)serializer.Deserialize(reader);
                        reader.ReadEndElement();
                        reader.ReadEndElement();
                        reader.MoveToContent();
                        this.Add(id, value);
                    }
                    reader.Read();
                }
            }
        }

        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T), "");
            foreach (object key in this.Keys)
            {
                object value = this[key];
                writer.WriteStartElement("item");
                writer.WriteElementString("key", key.ToString());
                writer.WriteStartElement("value");                
                serializer.Serialize(writer, value);
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
        }
    }*/
}
